/*
 *  author: Honrun
 */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include "DevicesQueue.h"


QueueType g_TypeQueueUart0Read = {0};
static uint8_t st_ucQueueUart0ReadBuff[QUEUE_UART0_READ_LENGTH] = {0};
QueueType g_TypeQueueUart1Read = {0};
static uint8_t st_ucQueueUart1ReadBuff[QUEUE_UART1_READ_LENGTH] = {0};
QueueType g_TypeQueueUart2Read = {0};
static uint8_t st_ucQueueUart2ReadBuff[QUEUE_UART2_READ_LENGTH] = {0};
QueueType g_TypeQueueUart3Read = {0};
static uint8_t st_ucQueueUart3ReadBuff[QUEUE_UART3_READ_LENGTH] = {0};

QueueType g_TypeQueueKeyInput = {0};
static uint8_t st_ucQueueKeyInputBuff[QUEUE_KEY_INPUT_LENGTH] = {0};


enumQueueState enumQueueInit(void)
{
    enumQueueState enumState = queueNormal;

    if(enumQueueCreate(&g_TypeQueueUart0Read,   "Uart 0 Read",  st_ucQueueUart0ReadBuff,    sizeof(st_ucQueueUart0ReadBuff),    queueModeLock) != queueNormal)
        enumState = queueError;
    if(enumQueueCreate(&g_TypeQueueUart1Read,   "Uart 1 Read",  st_ucQueueUart1ReadBuff,    sizeof(st_ucQueueUart1ReadBuff),    queueModeLock) != queueNormal)
        enumState = queueError;
    if(enumQueueCreate(&g_TypeQueueUart2Read,   "Uart 2 Read",  st_ucQueueUart2ReadBuff,    sizeof(st_ucQueueUart2ReadBuff),    queueModeLock) != queueNormal)
        enumState = queueError;
    if(enumQueueCreate(&g_TypeQueueUart3Read,   "Uart 3 Read",  st_ucQueueUart3ReadBuff,    sizeof(st_ucQueueUart3ReadBuff),    queueModeLock) != queueNormal)
        enumState = queueError;

    if(enumQueueCreate(&g_TypeQueueKeyInput,    "Key Input",    st_ucQueueKeyInputBuff,     sizeof(st_ucQueueKeyInputBuff),     queueModeLock) != queueNormal)
        enumState = queueError;

    if(enumState != queueNormal)
        printf("enumQueueInit error.\r\n");

    return enumState;
}

/*
 * Return:      创建是否成功状态值
 * Parameters:  *ptypeQueue: 队列结构体指针; pucName: 队列名称; iLength: 队列长度（必须是2的n次方）
 * Description: 初始化队列
 */
enumQueueState enumQueueCreate(QueueType *ptypeQueue, char *pcName, uint8_t *pucBuff, int32_t iLength, enumQueueMode enumMode)
{
    if(ptypeQueue == NULL)
        return queueNull;

    if((pucBuff == NULL) || (iLength < 2))
        return queueEmpty;

    ptypeQueue->mode    = enumMode;
    ptypeQueue->name    = pcName;
    ptypeQueue->length  = iLength - 1;
    ptypeQueue->in      = 0;
    ptypeQueue->out     = 0;
    ptypeQueue->buff    = pucBuff;

    return queueNormal;
}

/*
 * Return:      void
 * Parameters:  *ptypeQueue: 队列结构体指针; enumState: 空满状态
 * Description: 设置队列缓存空满状态
 */
enumQueueState enumQueueSetState(QueueType *ptypeQueue, enumQueueState enumState)
{
    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return queueNull;

    if(enumState == queueEmpty)
        ptypeQueue->out = ptypeQueue->in = 0;

    return queueNormal;
}

/*
 * Return:      查找到的数据位置
 * Parameters:
 * Description: memrchr替代函数
 */
static void *pvQueueMemrchr(void *pvHandle, uint8_t ucByte, int32_t iCount)
{
    uint8_t *pucByte = pvHandle;

    for(pucByte += iCount - 1; iCount > 0; --iCount, --pucByte)
    {
        if(*pucByte == ucByte)
            return pucByte;
    }

    return NULL;
}

/*
 * Return:      队列缓存中有效数据长度
 * Parameters:  *ptypeQueue: 队列结构体指针
 * Description: 获取队列缓存中有效数据长度
 */
int32_t iQueueGetLength(QueueType *ptypeQueue)
{
    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return 0;

    return ptypeQueue->in - ptypeQueue->out;
}

/*
 * Return:      队列缓存中有效数据长度
 * Parameters:  *ptypeQueue: 队列结构体指针; ucByte: 指定的有效字节
 * Description: 获取队列缓存中有效数据长度，需要有指定的有效字节
 */
int32_t iQueueGetLengthNeed(QueueType *ptypeQueue, uint8_t ucByte)
{
    uint8_t *pucByte;
    int32_t iLength, iLengthTail;

    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return 0;

    iLength = ptypeQueue->in - ptypeQueue->out;

    iLengthTail = ptypeQueue->length + 1 - (ptypeQueue->out & ptypeQueue->length);
    iLengthTail = iLengthTail < iLength ? iLengthTail : iLength;

    if((pucByte = pvQueueMemrchr(ptypeQueue->buff, ucByte, iLength - iLengthTail)) != NULL)
        iLength = pucByte - ptypeQueue->buff + iLengthTail + 1;

    else if((pucByte = pvQueueMemrchr(ptypeQueue->buff + (ptypeQueue->out & ptypeQueue->length), ucByte, iLengthTail)) != NULL)
        iLength = pucByte - (ptypeQueue->buff + (ptypeQueue->out & ptypeQueue->length)) + 1;

    else
        iLength = 0;

    return iLength;
}

/*
 * Return:      队列缓存中到下一个分隔符的有效数据长度
 * Parameters:  *ptypeQueue: 队列结构体指针; ucByte: 指定的有效字节
 * Description: 获取队列缓存中有效数据长度
 */
int32_t iQueueGetLengthSeparetor(QueueType *ptypeQueue, uint8_t ucByte)
{
    uint8_t *pucByte;
    int32_t iLength, iLengthTail;

    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return 0;

    iLength = ptypeQueue->in - ptypeQueue->out;

    iLengthTail = ptypeQueue->length + 1 - (ptypeQueue->out & ptypeQueue->length);
    iLengthTail = iLengthTail < iLength ? iLengthTail : iLength;

    if((pucByte = memchr(ptypeQueue->buff + (ptypeQueue->out & ptypeQueue->length), ucByte, iLengthTail)) != NULL)
        iLength = pucByte - (ptypeQueue->buff + (ptypeQueue->out & ptypeQueue->length)) + 1;

    else if((pucByte = memchr(ptypeQueue->buff, ucByte, iLength - iLengthTail)) != NULL)
        iLength = pucByte - ptypeQueue->buff + iLengthTail + 1;

    else
        iLength = 0;

    return iLength;
}

/*
 * Return:      队列缓存中剩余长度
 * Parameters:  *ptypeQueue: 队列结构体指针
 * Description: 获取队列缓存中剩余长度
 */
int32_t iQueueGetLengthFree(QueueType *ptypeQueue)
{
    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return 0;

    return ptypeQueue->length + 1 - (ptypeQueue->in - ptypeQueue->out);
}

/*
 * Return:      是否入队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; ucByte: 待入队字节数据
 * Description: 入队一个字节数据
 */
enumQueueState enumQueuePushByte(QueueType *ptypeQueue, uint8_t ucByte)
{
    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL))
        return queueNull;

    if((ptypeQueue->in - ptypeQueue->out) > ptypeQueue->length)
    {
        if(ptypeQueue->mode == queueModeLock)
            return queueFull;

        /* 在溢出时，需要把出队指向当前队列新的末尾 */
        ptypeQueue->out = ptypeQueue->in - (ptypeQueue->length + 1);
    }

    ptypeQueue->buff[ptypeQueue->in++ & ptypeQueue->length] = ucByte;

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pucByte: 待出队字节数据指针
 * Description: 出队一个字节数据
 */
enumQueueState enumQueuePopByte(QueueType *ptypeQueue, uint8_t *pucByte)
{
    enumQueueState enumState;

    if((enumState = enumQueueViewByte(ptypeQueue, pucByte)) == queueNormal)
        ++ptypeQueue->out;

    return enumState;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pucByte: 待出队字节数据指针
 * Description: 出队一个字节数据，并保留队列中的原数据
 */
enumQueueState enumQueueViewByte(QueueType *ptypeQueue, uint8_t *pucByte)
{
    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL) || (pucByte == NULL))
        return queueNull;

    if(ptypeQueue->in == ptypeQueue->out)
      return queueEmpty;

    *pucByte = ptypeQueue->buff[ptypeQueue->out & ptypeQueue->length];

    return queueNormal;
}

/*
 * Return:      是否入队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pvBuff: 待入队数据缓存指针; iLength: 缓存长度
 * Description: 入队一系列数据
 */
enumQueueState enumQueuePushDatas(QueueType *ptypeQueue, void *pvBuff, int32_t iLength)
{
    int32_t iLengthTail;

    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL) || (pvBuff == NULL) || (iLength < 1))
        return queueNull;

    if((ptypeQueue->length + 1 - (ptypeQueue->in - ptypeQueue->out)) < iLength)
    {
        if(ptypeQueue->mode == queueModeLock)
            return queueFull;

        /* 在溢出时，需要把出队指向当前队列新的末尾 */
        ptypeQueue->out = ptypeQueue->in - (ptypeQueue->length + 1);
    }

    iLengthTail = ptypeQueue->length + 1 - (ptypeQueue->in & ptypeQueue->length);
    iLengthTail = iLengthTail < iLength ? iLengthTail : iLength;

    memcpy(ptypeQueue->buff + (ptypeQueue->in & ptypeQueue->length), pvBuff, iLengthTail);
    memcpy(ptypeQueue->buff, (uint8_t *)pvBuff + iLengthTail, iLength - iLengthTail);

    ptypeQueue->in += iLength;

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pvBuff: 待出队数据缓存指针; iLength: 缓存长度
 * Description: 出队一系列数据
 */
enumQueueState enumQueuePopDatas(QueueType *ptypeQueue, void *pvBuff, int32_t iLength)
{
    enumQueueState enumState;

    if((enumState = enumQueueViewDatas(ptypeQueue, pvBuff, iLength)) == queueNormal)
        ptypeQueue->out += iLength;

    return enumState;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pvBuff: 待出队数据缓存指针; iLength: 缓存长度
 * Description: 出队一系列数据，并保留队列中的原数据
 */
enumQueueState enumQueueViewDatas(QueueType *ptypeQueue, void *pvBuff, int32_t iLength)
{
    int32_t iLengthTail;

    if((ptypeQueue == NULL) || (ptypeQueue->buff == NULL) || (pvBuff == NULL) || (iLength < 1))
        return queueNull;

    if((ptypeQueue->in - ptypeQueue->out) < iLength)
        return queueEmpty;

    iLengthTail = ptypeQueue->length + 1 - (ptypeQueue->out & ptypeQueue->length);
    iLengthTail = iLengthTail < iLength ? iLengthTail : iLength;

    memcpy(pvBuff, ptypeQueue->buff + (ptypeQueue->out & ptypeQueue->length), iLengthTail);
    memcpy((uint8_t *)pvBuff + iLengthTail, ptypeQueue->buff, iLength - iLengthTail);

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pvBuff: 待出队数据缓存指针; iLength: 缓存长度; ucByte: 指定的有效字节
 * Description: 出队一系列数据，需要有指定的有效字节
 */
enumQueueState enumQueuePopDatasNeed(QueueType *ptypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte)
{
    enumQueueState enumState;

    if((enumState = enumQueueViewDatasNeed(ptypeQueue, pvBuff, iLength, ucByte)) == queueNormal)
        ptypeQueue->out += iLength;

    return enumState;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *ptypeQueue: 队列结构体指针; *pvBuff: 待出队数据缓存指针; iLength: 缓存长度; ucByte: 指定的有效字节
 * Description: 出队一系列数据，需要有指定的有效字节，并保留队列中的原数据
 */
enumQueueState enumQueueViewDatasNeed(QueueType *ptypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte)
{
    if(iQueueGetLengthNeed(ptypeQueue, ucByte) < iLength)
        return queueEmpty;

    return enumQueueViewDatas(ptypeQueue, pvBuff, iLength);
}
